package de.unikoblenz.west.csxpoi.server.connector;

import java.util.ArrayList;
import java.util.List;

import org.openrdf.query.Binding;
import org.openrdf.query.BindingSet;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.RepositoryException;

import de.unikoblenz.west.csxpoi.server.CategoryWrapper;
import de.unikoblenz.west.csxpoi.server.Constants;
import de.unikoblenz.west.csxpoi.server.PoiWrapper;
import de.unikoblenz.west.csxpoi.server.ServerException;
import de.unikoblenz.west.csxpoi.server.XmlWriter;

/**
 * REST Connector to STEVIE datastore
 * 
 * @author Yassin Nachite
 *
 */
public class StevieRESTConnector extends SesameConnector {

	public StevieRESTConnector(String serverAdress, String repositoryID) {
		super(serverAdress, repositoryID);
	}

	@Override
	List<BindingSet> sendRequest(String rdfQuery) {
		try {
			try {
				connection = repository.getConnection();
				ArrayList<BindingSet> resultList = new ArrayList<BindingSet>();
				TupleQuery query = connection.prepareTupleQuery(
						QueryLanguage.SPARQL, rdfQuery);
				TupleQueryResult result = query.evaluate();

				try {
					while (result.hasNext()) {
						resultList.add(result.next());
					}
					return resultList;
				} catch (QueryEvaluationException e) {
					throw new ServerException();
				} finally {
					result.close();
					connection.close();
				}

			} catch (QueryEvaluationException e) {
				throw new ServerException();
			} catch (RepositoryException e) {
				throw new ServerException();
			} catch (MalformedQueryException e) {
				throw new ServerException();
			}

		} catch (ServerException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<String> formatResult(String result) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<String> baseRequest(String[] args) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<String> contributionRequest(String[] args) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<PoiWrapper> poiRequest(String[] args) {
		String query = "";

		if (args[0] != null && !args[0].equals("")) {
			query = "PREFIX base: <"
					+ Constants.NS_BASE
					+ "> "
					+ "PREFIX geo: <"
					+ Constants.NS_GEO
					+ "> "
					+ "PREFIX rdfs: <"
					+ Constants.NS_RDFS
					+ "> "
					+ "PREFIX gle: <"
					+ Constants.NS_GLE
					+ "> "
					
					+ "SELECT DISTINCT ?poi ?name ?lat ?long ?alt ?start ?end WHERE {"
					+ " ?contribution a base:PoiContribution ;"
					+ "  base:issuedBy <" + args[0] + "> ;"
					+ "  base:affectsPoi ?poi." + "?poi geo:lat ?lat ;"
					+ "  geo:long ?long;  geo:alt ?alt; rdfs:label ?name."
					+ " OPTIONAL { ?poi gle:hasStartDateTime ?start . } "
					+ " OPTIONAL { ?poi gle:hasEndDateTime ?end . } "
					+ " OPTIONAL { ?removal a base:PoiRemoval ;"
					+ " base:affectsPoi ?poi . }"

					+ " FILTER (!bound(?removal) &&" + "  ?long >= " + args[2]
					+ " &&" + "  ?long <= " + args[3] + " &&" + "  ?lat <= "
					+ args[4] + " &&" + "  ?lat >= " + args[5] + " )" + "}";

		}

		else {

			query = "PREFIX base: <"
					+ Constants.NS_BASE
					+ "> "
					+ "PREFIX geo: <"
					+ Constants.NS_GEO
					+ "> "
					+ "PREFIX rdfs: <"
					+ Constants.NS_RDFS
					+ "> "
					+ "PREFIX gle: <"
					+ Constants.NS_GLE
					+ "> "									
					+ "SELECT DISTINCT ?poi ?name ?lat ?long ?alt ?start ?end WHERE {"
					+ " ?poi a base:Poi ;" + " geo:lat ?lat ;"
					+ "  geo:long ?long;  geo:alt ?alt; rdfs:label ?name."
					+ " OPTIONAL { ?poi gle:hasStartDateTime ?start . } "
					+ " OPTIONAL { ?poi gle:hasEndDateTime ?end . } "
					+ " OPTIONAL { ?removal a base:PoiRemoval ;"
					+ " base:affectsPoi ?poi . }"
					+ " FILTER (!bound(?removal) &&" + "  ?long >= " + args[2]
					+ " &&" + "  ?long <= " + args[3] + " &&" + "  ?lat <= "
					+ args[4] + " &&" + "  ?lat >= " + args[5] + " )" + "}";

		}

		ArrayList<BindingSet> resultList = (ArrayList) sendRequest(query);
		ArrayList<PoiWrapper> pois = new ArrayList<PoiWrapper>();
		if(resultList.size()>0)
		try {
			try {
				connection = repository.getConnection();
				for (BindingSet result : resultList) {

					PoiWrapper poi = PoiWrapper.createFromBinding(result,
							result.getValue("poi").stringValue(), connection);

					if (poi != null && !poi.isObsolete()
							&& poi.matchesQuery(args[1])) {
						poi.setType("Stevie");
						pois.add(poi);
					}

				}

				return pois;

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				connection.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public List<String> userRequest(String[] args) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<String> vocabularyRequest(String[] args) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<CategoryWrapper> categoryRequest(String[] args) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<String> formatResult(List<String> data) {
		// TODO Auto-generated method stub
		return null;
	}

}
